package com.example.cm_player.manager

import android.media.AudioAttributes
import android.media.MediaPlayer
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.example.cm_player.model.SongInfo
import com.example.cm_player.IMusicPlayer
import com.example.cm_player.model.PlayMode
import com.example.cm_player.StateMediaPlayer
import com.example.cm_player.cache.AudioCacheManager
import com.example.cm_player.cache.AudioDownloader
import com.example.cm_utils.ContextHelper
import com.example.cm_utils.NetworkUtil
import com.example.cm_utils.ToastUtil
import kotlin.random.Random

/**
 * 音乐播放器管理类，负责播放控制
 */
class PlayerManager private constructor() : IMusicPlayer,AudioFocusManager.AudioFocusChangeListener {
    private var notificationController: NotificationController? = null
    private val currentMusicList = mutableListOf<SongInfo>()
    private var player: StateMediaPlayer? = null
    private val handler = Handler(Looper.getMainLooper())
    private val audioFocusManager = AudioFocusManager.getInstance()
    private var currentPlayMode = PlayMode.LIST_LOOP //列表循环
    private var wasPlayingBeforeFocusLoss = false //记录失去音频焦点前是否正在播放
    private val updatePositionRunnable = object : Runnable {
        override fun run() {
            player?.let {
                if (it.isPlaying) {
                    PlayerStateManager.updateProgress(it.currentPosition.toLong())
                }
            }
            handler.postDelayed(this, 1000)
        }
    }

    companion object {
        private const val TAG = "PlayerManager"

        @Volatile
        private var instance: PlayerManager? = null

        fun getInstance(): PlayerManager {
            return instance ?: synchronized(this) {
                instance ?: PlayerManager().also { instance = it }
            }
        }
    }

    /**
     * 创建播放器
     */
    fun createNewPlayer() {
        if (player == null) {
            //初始化音频焦点管理器
            audioFocusManager.init()
            audioFocusManager.setAudioFocusChangeListener(this)

            player = StateMediaPlayer().apply {
                setAudioAttributes(
                    AudioAttributes.Builder()
                        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .build()
                )
                setPreparedListener {
                    addToPlaylist(PlayerStateManager.currentPlayedMusic.value!!)
                    this@PlayerManager.start()
                }
                setCompletionListener {
                    Log.v("wjb","setCompletionListener")
                    nextMusic()
                }
                setErrorListener(MediaPlayer.OnErrorListener { mp, what, extra ->
                    Log.d("StateMediaPlayer", "$what $extra")
                    val msg = when (what) {
                        -38 -> "网络连接不稳定，正在重试..."
                        MediaPlayer.MEDIA_ERROR_SERVER_DIED -> "播放器遇到问题，正在恢复..."
                        else -> when (extra) {
                            MediaPlayer.MEDIA_ERROR_IO -> "无法访问音频文件"
                            MediaPlayer.MEDIA_ERROR_MALFORMED,
                            MediaPlayer.MEDIA_ERROR_UNSUPPORTED -> "不支持的音频格式"
                            MediaPlayer.MEDIA_ERROR_TIMED_OUT -> "加载超时，请检查网络"
                            else -> "播放出错，请稍后再试"
                        }
                    }
                    return@OnErrorListener true
                })

                setOnStateChanged { state ->
                    when (state) {
                        StateMediaPlayer.State.IDLE -> {}
                        StateMediaPlayer.State.INITIALIZED -> {}
                        StateMediaPlayer.State.PREPARING -> {}
                        StateMediaPlayer.State.PREPARED -> {}
                        StateMediaPlayer.State.STARTED -> {}
                        StateMediaPlayer.State.PAUSED -> {}
                        StateMediaPlayer.State.STOPPED -> {}
                        StateMediaPlayer.State.COMPLETED -> {}
                        StateMediaPlayer.State.ERROR -> {}
                        StateMediaPlayer.State.END -> {}
                    }
                }
            }
        }
    }


    override fun start() {
        //请求音频焦点
        if(!audioFocusManager.requestAudioFocus()){
            ToastUtil.show("获取音频焦点失败")
            return
        }

        player?.let {
            try {
                it.start()
            } catch (e: IllegalStateException) {
                Log.w(TAG, "IllegalStateException msg:" + e.printStackTrace())
            } catch (e: Exception) {
                Log.w(TAG, "Exception msg:" + e.printStackTrace())
            }
        }
    }

    override fun play(songInfo: SongInfo) {
        Log.v(TAG, "PlayManager play songInfo:$songInfo")
        player?.let {
            PlayerStateManager.updateCurrentMusic(songInfo)
            PlayerStateManager.updatePlayingState(true)
            try {
                it.reset()
                val ctx = ContextHelper.context.get()!!
                val localPath = AudioCacheManager.getLocalPath(ctx, songInfo.id)
                val isOnline = NetworkUtil.isNetworkAvailable(ctx)
                if(localPath != null){
                    Log.v(TAG,"setDataSource from localPath")
                    it.setDataSource(localPath)
                    it.prepareAsync()
                }else if(isOnline){
                    Log.v(TAG,"setDataSource from network")
                    it.setDataSource(songInfo.playUrl)
                    it.prepareAsync()
                    val file = AudioCacheManager.buildTargetFile(ctx,songInfo.id)
                    AudioDownloader.downLoadToFile(songInfo.playUrl,file){result->
                        if(result){
                            AudioCacheManager.putLocalPath(ctx,songInfo.id,file)
                        }
                    }
                }else{
                    ToastUtil.show("此歌曲未缓存，离线不可播放")
                }
            } catch (e: IllegalStateException) {
                Log.w(TAG, "IllegalStateException :" + e.printStackTrace())
            } catch (e: Exception) {
                Log.w(TAG, "Exception :" + e.printStackTrace())
            }
        }
    }

    override fun pause() {
        player?.let {
            PlayerStateManager.updatePlayingState(false)
            try {
                it.pause()
            } catch (e: IllegalStateException) {
                Log.w(TAG, "IllegalStateException :" + e.printStackTrace())
            } catch (e: Exception) {
                Log.w(TAG, "Exception :" + e.printStackTrace())
            }
        }
    }

    override fun resume() {
        player?.let {
            PlayerStateManager.updatePlayingState(true)
            try {
                start()
            } catch (e: IllegalStateException) {
                Log.w(TAG, "IllegalStateException :" + e.printStackTrace())
            } catch (e: Exception) {
                Log.w(TAG, "Exception :" + e.printStackTrace())
            }
        }
    }

    override fun stop() {
        player?.let {
            try {
                it.stop()
            } catch (e: IllegalStateException) {
                Log.w(TAG, "IllegalStateException :" + e.printStackTrace())
            } catch (e: Exception) {
                Log.w(TAG, "Exception :" + e.printStackTrace())
            }
        }
    }

    override fun release() {
        handler.removeCallbacks(updatePositionRunnable)
        player?.let {
            if (it.isPlaying) {
                it.stop()
            }
            it.release()
            player = null
        }

        //释放音频焦点
        audioFocusManager.release()
        instance = null
    }

    override fun seekTo(position: Long) {
        player?.let {
            try {
                it.seekTo(position.toInt())
            } catch (e: IllegalStateException) {
                Log.w(TAG, "IllegalStateException :" + e.printStackTrace())
            } catch (e: Exception) {
                Log.w(TAG, "Exception :" + e.printStackTrace())
            }
        }
    }

    override fun setVolume(volume: Float) {
        player?.setVolume(volume, volume)
    }



    override fun nextMusic() {
        if (currentMusicList.isEmpty()) {
            ToastUtil.show("当前列表为空")
            return
        }

        try {
            when (currentPlayMode) {
                PlayMode.SINGLE_LOOP -> {
                    stop()
                    play(PlayerStateManager.currentPlayedMusic.value!!)
                }

                PlayMode.LIST_LOOP -> {
                    val nextIndex =
                        (currentMusicList.indexOf(PlayerStateManager.currentPlayedMusic.value) + 1) % currentMusicList.size
                    stop()
                    play(currentMusicList[nextIndex])
                }

                PlayMode.RANDOM -> {
                    if (currentMusicList.size == 1) {
                        stop()
                        play(PlayerStateManager.currentPlayedMusic.value!!)
                    } else {
                        var randomIndex =
                            currentMusicList.indexOf(PlayerStateManager.currentPlayedMusic.value)
                        while (randomIndex == currentMusicList.indexOf(PlayerStateManager.currentPlayedMusic.value)) {
                            randomIndex = Random.nextInt(currentMusicList.size)
                        }
                        stop()
                        play(currentMusicList[randomIndex])
                    }
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "nextMusic error: ${e.message}")
        }
    }

    override fun previousMusic() {

        if (currentMusicList.isEmpty()) {
            ToastUtil.show("当前列表为空")
            return
        }

        try {
            when (currentPlayMode) {
                PlayMode.SINGLE_LOOP -> {
                    stop()
                    play(PlayerStateManager.currentPlayedMusic.value!!)
                }

                PlayMode.LIST_LOOP -> {
                    val prevIndex =
                        (currentMusicList.indexOf(PlayerStateManager.currentPlayedMusic.value) - 1 + currentMusicList.size) % currentMusicList.size
                    stop()
                    play(currentMusicList[prevIndex])
                }

                PlayMode.RANDOM -> {
                    if (currentMusicList.size == 1) {
                        stop()
                        play(PlayerStateManager.currentPlayedMusic.value!!)
                    } else {
                        var randomIndex =
                            currentMusicList.indexOf(PlayerStateManager.currentPlayedMusic.value)
                        while (randomIndex == currentMusicList.indexOf(PlayerStateManager.currentPlayedMusic.value)) {
                            randomIndex = Random.nextInt(currentMusicList.size)
                        }
                        stop()
                        play(currentMusicList[randomIndex])
                    }
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "previousMusic error: ${e.message}")
        }
    }

    override fun addToPlaylist(songInfo: SongInfo) {
        if (!currentMusicList.contains(songInfo)) {
            currentMusicList.add(songInfo)
        }
    }

    override fun removeFromPlaylist(songInfo: SongInfo) {
        if (currentMusicList.contains(songInfo)) {
            currentMusicList.remove(songInfo)
        } else {
            ToastUtil.show("该元素不存在，移除失败")
        }
    }


    override fun setPlayMode(playMode: PlayMode) {
        Log.d("StateMediaPlayer","playmode:"+playMode.name)
        if (playMode == currentPlayMode) {
            return
        }
        currentPlayMode = playMode
        PlayerStateManager.updateCurrentPlayMode(playMode)
    }

    override fun getPlayMode() = currentPlayMode

    override fun addNewPlayList(newList: List<SongInfo>) {
        if (newList.isEmpty()) {
            return
        }
        clearMusicPlayList()
        currentMusicList.addAll(newList)
    }

    override fun clearMusicPlayList() {
        if (currentMusicList.size == 0) {
            return
        }
        currentMusicList.clear()
    }

    fun getCurrentPosition(): Long {
        return player?.currentPosition?.toLong() ?: 0L
    }

    override fun getCurrentMusicList() = currentMusicList

    fun getDuration(): Long {
        return player?.duration?.toLong() ?: 0L
    }

    fun setNotificationController(notificationController:NotificationController){
        this.notificationController = notificationController
    }

    interface NotificationController{
        fun updateNotification()
    }

    override fun onAudioFocusGained() {
        //当重新获得音频焦点时，如果之前正在播放，则恢复播放
        if(wasPlayingBeforeFocusLoss){
            resume()
            wasPlayingBeforeFocusLoss = false
        }
    }

    override fun onAudioFocusLost() {
        //永久失去焦点，停止播放
        wasPlayingBeforeFocusLoss = PlayerStateManager.isPlaying.value == true
        pause()
    }

    override fun onAudioFocusLostTransient() {
        // 短暂失去焦点，暂停播放
        wasPlayingBeforeFocusLoss = PlayerStateManager.isPlaying.value == true
        pause()
    }

    override fun onAudioFocusLostTransientCanDuck() {
        //当临时失去音频焦点但可以 duck 时，降低音量
        setVolume(0.2f)
    }
}